import { defineStore } from 'pinia'
import { authApi } from '@/api/auth'
import { removeToken, setToken, getToken, updateAxiosAuthHeader } from '@/utils/auth'
import type { UserInfo, LoginRequest, LoginResponse } from '@/types/api'
import type { UserSettings } from '@/types/system'
import router from '@/router'
import { getRememberMe, setRememberMe, clearAuthStorage } from '@/config/storage'

interface UserState {
  token: string
  refreshToken: string
  sessionId?: string
  permVersion?: number
  userInfo: UserInfo | null
  roles: string[]
  permissions: Set<string>
  menus: any[]  // ✅ 优化：存储登录时返回的树形菜单（避免额外API调用）
  settings: UserSettings
  isLoggingOut?: boolean
  // ✅ 优化：添加权限检查缓存
  permissionCache?: Map<string, boolean>
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    token: getToken() || '',
    refreshToken: '',
    sessionId: undefined,
    permVersion: undefined,
    userInfo: null,
    roles: [],
    permissions: new Set(),
    menus: [],  // ✅ 初始化菜单数组
    settings: {
      theme: 'light',
      language: 'zh-CN',
      sidebarCollapsed: false,
      showBreadcrumb: true,
      showTabs: true,
      fixedHeader: true
    },
    isLoggingOut: false,
    permissionCache: new Map()  // ✅ 初始化权限缓存
  }),

  getters: {
    // 是否已登录
    isLoggedIn: (state): boolean => !!state.token,
    
    // 获取用户名
    username: (state): string => state.userInfo?.username || '',
    
    // 获取昵称
    nickname: (state): string => state.userInfo?.nickname || state.userInfo?.username || '',
    
    // 获取头像
    avatar: (state): string => state.userInfo?.avatarUrl || '',
    
    // 获取用户角色列表
    userRoles: (state): string[] => state.roles,
    
    // 获取权限列表
    userPermissions: (state): string[] => Array.from(state.permissions),
    
    // 是否为超级管理员（与后端逻辑保持一致，只认SUPER_ADMIN）
    isSuperAdmin: (state): boolean => {
      const rolesUp = state.roles.map(r => String(r).toUpperCase())
      return rolesUp.includes('SUPER_ADMIN')
    },
    
    // 租户ID
    tenantId: (state): string => state.userInfo?.tenantId || 'default',
    
    // 部门ID
    deptId: (state): string => state.userInfo?.deptId || ''
  },

  actions: {
    // 用户登录
    async login(loginData: LoginRequest & { rememberMe?: boolean }): Promise<LoginResponse> {
      try {
        console.log('🔐 发起登录请求...')
        
        // ✅ 根据用户选择设置"记住我"
        if (loginData.rememberMe !== undefined) {
          setRememberMe(loginData.rememberMe)
          console.log(`💾 用户选择${loginData.rememberMe ? '记住' : '不记住'}登录状态`)
        }
        
        // ✅ 登录前清理旧的路由和权限数据，避免版本不一致
        try {
          const { usePermissionStore } = await import('./permission')
          const permissionStore = usePermissionStore()
          
          // 检查是否有旧数据需要清理
          if (permissionStore.menuLoaded || permissionStore.permVersion !== undefined) {
            console.log('🧹 检测到旧的权限数据，清理中...', {
              oldPermVersion: permissionStore.permVersion,
              menuLoaded: permissionStore.menuLoaded
            })
            permissionStore.resetRoutes()
          }
        } catch (e) {
          console.warn('清理旧权限数据失败（不影响登录）:', e)
        }
        
        const response = await authApi.login(loginData)
        const { accessToken, refreshToken, sessionId, permVersion, userInfo, authInfo } = response.data
        
        console.log(`✅ 登录成功，接收到新token和权限版本: ${accessToken?.substring(0, 8)}..., permVersion=${permVersion}`)
        
        // 🔧 立即更新token（会自动更新axios header）
        this.token = accessToken
        this.refreshToken = refreshToken
        setToken(accessToken) // 这会立即更新axios defaults
        this.sessionId = sessionId
        this.permVersion = permVersion
        
        // 🔧 双重保险：确保axios header立即更新
        updateAxiosAuthHeader(accessToken)
        
        // 保存用户信息
        this.userInfo = userInfo
        this.roles = userInfo.roles?.map(role => role.roleCode) || []
        
        // ✅ 如果后端返回了 authInfo，直接使用权限数据（减少额外API调用）
        if (authInfo?.permissions?.length) {
          this.setPermissions(authInfo.permissions)
        }
        
        // ✅ 优化：保存登录时返回的树形菜单（避免额外API调用）
        if (authInfo?.menus?.length) {
          this.menus = authInfo.menus
          console.log(`📜 已保存登录返回的树形菜单: ${this.menus.length}个根菜单`)
        }
        
        console.log('🎉 用户状态已更新，token已生效')
        
        // ✅ 优化：不在登录时加载路由，完全交给路由守卫处理
        // 避免重复加载，路由守卫会自动检查并加载菜单
        console.log('📌 路由将在路由守卫中自动加载')
        
        return response.data
      } catch (error) {
        console.error('登录失败:', error)
        throw error
      }
    },

    // 获取用户信息
    async getUserInfo(): Promise<UserInfo> {
      try {
        const response = await authApi.getCurrentUser()
        const userInfo = response.data
        
        this.userInfo = userInfo
        this.roles = userInfo.roles?.map(role => role.roleCode) || []
        
        // 处理 permVersion：优先使用后端返回值，其次保持现有值
        if (typeof userInfo.permVersion === 'number') {
          this.permVersion = userInfo.permVersion
        }
        // 如果后端没有返回且当前为 undefined，使用时间戳作为降级方案
        else if (this.permVersion === undefined) {
          this.permVersion = Date.now()
        }
        // 否则保持现有的 permVersion 不变（从登录时获取或从 localStorage 恢复）
        
        return userInfo
      } catch (error) {
        console.error('获取用户信息失败:', error)
        throw error
      }
    },

    // 刷新token
    async refreshUserToken(): Promise<void> {
      try {
        if (!this.refreshToken) {
          throw new Error('没有刷新token')
        }
        
        console.log('🔄 刷新token...')
        const response = await authApi.refreshToken({
          refreshToken: this.refreshToken,
          tenantId: this.tenantId
        })
        
        const { accessToken, refreshToken, permVersion, authInfo } = response.data
        
        // 🔧 立即更新token（会自动更新axios header）
        this.token = accessToken
        this.refreshToken = refreshToken
        setToken(accessToken) // 这会立即更新axios defaults
        
        // 🔧 双重保险：确保axios header立即更新
        updateAxiosAuthHeader(accessToken)
        
        // ✅ 如果后端返回了权限数据，同步更新
        if (authInfo?.permissions?.length) {
          this.setPermissions(authInfo.permissions)
        }
        
        // ✅ 优化：保存刷新Token时返回的树形菜单（避免额外API调用）
        if (authInfo?.menus?.length) {
          this.menus = authInfo.menus
          console.log(`📜 已保存刷新Token返回的树形菜单: ${this.menus.length}个根菜单`)
        }
        
        console.log(`✅ Token刷新成功: ${accessToken?.substring(0, 8)}...`)
        
        if (typeof permVersion === 'number' && permVersion !== this.permVersion) {
          this.onPermVersionChanged(permVersion)
        }
      } catch (error) {
        // 只在非认证错误时打印详细日志（认证失败是预期内的，不需要详细日志）
        if (error && typeof error === 'object' && 'response' in error) {
          const axiosError = error as any
          if (axiosError.response?.status !== 401) {
            console.error('刷新token失败:', error)
          }
        } else {
          console.error('刷新token失败:', error)
        }
        // 不在这里调用 logout()，由 request.ts 的拦截器统一处理
        throw error
      }
    },

    // 用户登出
    async logout(options?: { serverCall?: boolean; reason?: string }): Promise<void> {
      try {
        if (this.isLoggingOut) return
        this.isLoggingOut = true
        const serverCall = options?.serverCall !== false
        const reason = options?.reason || 'manual'
        const tokenSnapshot = this.token
        const sessionIdSnapshot = this.sessionId
        if (serverCall && tokenSnapshot) {
          await authApi.logout({
            logoutReason: reason,
            accessToken: tokenSnapshot,
            sessionId: sessionIdSnapshot
          })
        }
      } catch (error) {
        console.error('登出请求失败:', error)
      } finally {
        // 清除本地数据
        this.clearUserData()
        
        // 跳转到登录页
        if (router.currentRoute.value.path !== '/login') {
          router.push('/login')
        }
        this.isLoggingOut = false
      }
    },

    // 强制登出（token无效时）
    forceLogout(): void {
      if (this.isLoggingOut) return
      this.isLoggingOut = true
      try {
        this.clearUserData()
        if (router.currentRoute.value.path !== '/login') {
          router.push('/login')
        }
      } finally {
        this.isLoggingOut = false
      }
    },

    // 清除用户数据
    clearUserData(): void {
      this.token = ''
      this.refreshToken = ''
      this.sessionId = undefined
      this.permVersion = undefined
      this.userInfo = null
      this.roles = []
      this.permissions.clear()
      this.menus = []  // ✅ 优化：清空菜单数据
      // ✅ 优化：清空权限缓存
      if (this.permissionCache) {
        this.permissionCache.clear()
      }
      removeToken()
      
      // ✅ 如果用户不记住登录，清除所有持久化数据
      if (!getRememberMe()) {
        console.log('💾 用户未勾选"记住我"，清除所有持久化数据')
        clearAuthStorage()
      }
      
      // 同时清空动态路由状态，避免残留 menuLoaded 导致后续不生成
      try {
        // 动态导入以避免循环依赖
        ;(async () => {
          const { usePermissionStore } = await import('./permission')
          const permissionStore = usePermissionStore()
          permissionStore.resetRoutes()
        })()
      } catch {}
    },

    // ✅ 优化：权限版本变更处理，改进用户体验
    async onPermVersionChanged(newVersion: number): Promise<void> {
      console.warn(`🔄 权限版本变更: ${this.permVersion} -> ${newVersion}`)
      
      const oldVersion = this.permVersion
      this.permVersion = newVersion
      
      try {
        const { usePermissionStore } = await import('./permission')
        const permissionStore = usePermissionStore()
        
        // 先获取新的菜单和权限（不清空旧数据）
        console.log('📥 获取新的菜单和权限...')
        await permissionStore.generateRoutes()
        
        // 显示友好提示
        const { ElNotification } = await import('element-plus')
        ElNotification({
          title: '权限已更新',
          message: '您的权限已更新，部分功能可能发生变化',
          type: 'warning',
          duration: 5000
        })
        
        console.log('✅ 权限更新完成')
        
      } catch (e) {
        console.error('权限更新失败:', e)
        this.permVersion = oldVersion  // 回滚版本号
        
        const { ElMessage } = await import('element-plus')
        ElMessage.error('权限更新失败，请刷新页面')
      }
    },

    // ✅ 优化：统一的权限检查方法（带缓存，支持 any/all 模式）
    hasPermission(permission: string | string[], mode: 'any' | 'all' = 'any'): boolean {
      // 超级管理员跳过检查
      if (this.isSuperAdmin) {
        return true
      }
      
      // 生成缓存key（包含模式）
      const key = Array.isArray(permission) 
        ? `${mode}:${permission.sort().join(',')}` 
        : permission
      
      // 检查缓存
      if (this.permissionCache?.has(key)) {
        return this.permissionCache.get(key)!
      }
      
      // 计算结果
      let result: boolean
      if (Array.isArray(permission)) {
        result = mode === 'all'
          ? permission.every(p => this.permissions.has(p))
          : permission.some(p => this.permissions.has(p))
      } else {
        result = this.permissions.has(permission)
      }
      
      // 存入缓存
      if (!this.permissionCache) {
        this.permissionCache = new Map()
      }
      this.permissionCache.set(key, result)
      
      return result
    },

    // 检查角色
    hasRole(role: string | string[]): boolean {
      if (Array.isArray(role)) {
        return role.some(r => this.roles.includes(r))
      } else {
        return this.roles.includes(role)
      }
    },

    // ✅ 优化：保留为便捷方法（内部调用统一的 hasPermission）
    hasAnyPermission(permissions: string[]): boolean {
      return this.hasPermission(permissions, 'any')
    },

    // ✅ 优化：保留为便捷方法（内部调用统一的 hasPermission）
    hasAllPermissions(permissions: string[]): boolean {
      return this.hasPermission(permissions, 'all')
    },

    // 更新用户设置
    updateSettings(newSettings: Partial<UserSettings>): void {
      this.settings = { ...this.settings, ...newSettings }
    },

    // 切换主题
    toggleTheme(): void {
      this.settings.theme = this.settings.theme === 'light' ? 'dark' : 'light'
    },

    // 切换侧边栏折叠状态
    toggleSidebarCollapse(): void {
      this.settings.sidebarCollapsed = !this.settings.sidebarCollapsed
    },

    // 设置权限列表
    setPermissions(permissions: string[]): void {
      this.permissions = new Set(permissions)
      // ✅ 优化：清空权限缓存
      if (this.permissionCache) {
        this.permissionCache.clear()
      }
    },

    // 添加权限
    addPermission(permission: string): void {
      this.permissions.add(permission)
    },

    // 移除权限
    removePermission(permission: string): void {
      this.permissions.delete(permission)
    },

    // 设置用户信息
    setUserInfo(userInfo: UserInfo): void {
      this.userInfo = userInfo
      this.roles = userInfo.roles?.map(role => role.roleCode) || []
    },

    // 更新用户头像
    updateAvatar(avatarUrl: string): void {
      if (this.userInfo) {
        this.userInfo.avatarUrl = avatarUrl
      }
    },

    // 检查token是否即将过期
    isTokenExpiringSoon(thresholdMinutes: number = 10): boolean {
      if (!this.token) {
        return false
      }
      
      try {
        // 解析JWT token获取过期时间
        const payload = JSON.parse(atob(this.token.split('.')[1]))
        const expirationTime = payload.exp * 1000
        const currentTime = Date.now()
        const thresholdTime = thresholdMinutes * 60 * 1000
        
        return (expirationTime - currentTime) <= thresholdTime
      } catch {
        return false
      }
    }
  },

  // 持久化配置
  persist: {
    key: 'kexio-user-store',
    // ✅ 统一使用 localStorage，通过启动时检查和登出时清除来实现"记住我"功能
    storage: localStorage,
    paths: ['token', 'refreshToken', 'userInfo', 'roles', 'permissions', 'settings', 'permVersion', 'sessionId'],
    // ✅ 自定义序列化：处理 Set 和 Map 类型（permissions 是 Set，需要特殊处理）
    serializer: {
      serialize: (state: any) => {
        const serialized = { ...state }
        // 将 Set 转为数组
        if (state.permissions instanceof Set) {
          serialized.permissions = Array.from(state.permissions)
        }
        // 将 Map 转为对象
        if (state.permissionCache instanceof Map) {
          serialized.permissionCache = Object.fromEntries(state.permissionCache)
        }
        return JSON.stringify(serialized)
      },
      deserialize: (value: string) => {
        const parsed = JSON.parse(value)
        // 将数组转回 Set
        if (Array.isArray(parsed.permissions)) {
          parsed.permissions = new Set(parsed.permissions)
        }
        // 将对象转回 Map
        if (parsed.permissionCache && typeof parsed.permissionCache === 'object') {
          parsed.permissionCache = new Map(Object.entries(parsed.permissionCache))
        }
        return parsed
      }
    }
  }
})
